#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;

const int N = 1e6 + 5;

#define LEFT_CHILD(id) (id << 1)
#define RIGHT_CHILD(id) (id << 1 | 1)
#define LEFT_RANGE LEFT_CHILD(id), l, mid
#define RIGHT_RANGE RIGHT_CHILD(id), mid + 1, r
string s;

// 线段树节点定义
struct Node {
  int length;     // 区间长度
  int leftMax;    // 左端点开始的最长连续相同字符长度
  int rightMax;   // 右端点结束的最长连续相同字符长度
  int totalMax;   // 区间内最长连续相同字符长度
  char leftChar;  // 左端点字符
  char rightChar; // 右端点字符
};

Node segTree[N * 4];

// 合并两个子节点的信息 ( mergeNodes)
Node pushUp(const Node &left, const Node &right) {
  Node result;

  result.leftChar = left.leftChar;
  result.rightChar = right.rightChar;
  result.totalMax = max(left.totalMax, right.totalMax);

  // 如果中间字符相同，可以合并左右区间
  if (left.rightChar == right.leftChar) {
    result.totalMax = max(result.totalMax, left.rightMax + right.leftMax);
  }

  result.leftMax = left.leftMax;
  if (left.leftMax == left.length && left.rightChar == right.leftChar) {
    result.leftMax += right.leftMax;
  }

  result.rightMax = right.rightMax;
  if (right.rightMax == right.length && left.rightChar == right.leftChar) {
    result.rightMax += left.rightMax;
  }

  result.length = left.length + right.length;
  return result;
}

// 构建线段树
void buildSegmentTree(int id, int l, int r) {
  if (l == r) {
    segTree[id] = {1, 1, 1, 1, s[l], s[l]};
    return;
  }
  int mid = (l + r) >> 1;
  buildSegmentTree(LEFT_RANGE);
  buildSegmentTree(RIGHT_RANGE);
  segTree[id] = pushUp(segTree[LEFT_CHILD(id)], segTree[RIGHT_CHILD(id)]);
}

// 修改线段树
void updateSegment(int id, int l, int r, int pos, char newChar) {
  if (pos < l || pos > r)
    return;

  if (l == r) {
    segTree[id] = {1, 1, 1, 1, newChar, newChar};
    return;
  }

  int mid = (l + r) >> 1;
  if (pos <= mid) {
    updateSegment(LEFT_RANGE, pos, newChar);
  } else {
    updateSegment(RIGHT_RANGE, pos, newChar);
  }
  segTree[id] = pushUp(segTree[LEFT_CHILD(id)], segTree[RIGHT_CHILD(id)]);
}

// 查询线段树
Node querySegment(int id, int l, int r, int ql, int qr) {
  if (ql <= l && qr >= r) {
    return segTree[id];
  }

  int mid = (l + r) >> 1;
  if (qr <= mid) {
    return querySegment(LEFT_RANGE, ql, qr);
  }
  if (ql > mid) {
    return querySegment(RIGHT_RANGE, ql, qr);
  }

  return pushUp(querySegment(LEFT_RANGE, ql, qr),
                querySegment(RIGHT_RANGE, ql, qr));
}

int main() {
  int n, q;
  cin >> n >> q >> s;
  s = " " + s; // 使索引从1开始

  buildSegmentTree(1, 1, n);

  while (q--) {
    int operationType;
    cin >> operationType;

    if (operationType == 1) {
      int position;
      char newChar;
      cin >> position >> newChar;
      updateSegment(1, 1, n, position, newChar);
    } else {
      int left, right;
      cin >> left >> right;
      Node result = querySegment(1, 1, n, left, right);
      cout << result.totalMax << endl;
    }
  }

  return 0;
}